home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 016 / 26time11.arc / 26TIME.ASM next >
Encoding:
Assembly Source File  |  1986-11-28  |  13.9 KB  |  487 lines

  1. ;--------------------------------------------------------------------------
  2. ;-------------------------------  26TIME v1.0  ----------------------------
  3. ;--------------------------------------------------------------------------
  4. ;
  5. ;  PROGRAM   26TIME
  6. ;  VERSION   1.1
  7. ;  AUTHOR    PETER NELSON
  8. ;
  9. ;  DESCRIPTION:
  10. ;
  11. ;  This program is designed for use with the IBM-CGA card.  It resets the
  12. ;  6485 chip to display 26 instead of the normal 25 rows of text on the
  13. ;  screen.  On the 26th line is displayed the time, updated 1nc per minute.
  14. ;  It is theoretically possible to use this program with a normal graphics
  15. ;  card.  You would have to put the time in the upper right corner, and check
  16. ;  18 times/second to see if it had scrolled off the screen yet.  If it had,
  17. ;  you would have to redisplay it.  This program checks twice/second the 
  18. ;  the color of the lower-right character of the screen.  It then prints the
  19. ;  26th row that color, and displays the time using that color too.  This 
  20. ;  makes it look good no matter what program you are running.  If the color
  21. ;  of the lower-right character changes, it redraws the entire bottom line,
  22. ;  including the time.  Every time the time is displayed, there is a quiet
  23. ;  "tick" sound made.  It is possible to have the seconds being displayed
  24. ;  as they change, or have the colon flash once/second, but I decided this
  25. ;  would eat up too much processor power.
  26. ;
  27. ;
  28. ;  REVISIONS:
  29. ;
  30. ;  VERSION #    AUTHOR        DESCRIPTION
  31. ;
  32. ;        1.1    Peter Nelson    Some programs would blank the screen by
  33. ;                a hardware method that also ended up blanking
  34. ;                my time display.  Added a check to see if
  35. ;                the last position on the 26th line had an
  36. ;                'm'.  If not, I redisplayed.  This makes it
  37. ;                compatible with Lotus-123.
  38. ;
  39. ;------------------------------  INCLUDES  --------------------------------
  40.  
  41. include    \asm\macros.asm        ; defines the IFR macro
  42. include    \asm\equates.asm    ; has many generally used values equated
  43.  
  44. ;------------------------------  PUBLICS  ---------------------------------
  45. ;
  46. ; The public directive allows the use of these labels by the symbolic
  47. ; debugger (SYMDEB).
  48.  
  49.  
  50. public    start, begin, setvectors, int18_routine, int18_cont1, exit
  51. public    checkrow, check_cont0, check_cont1, checkrow_exit
  52. public    checkrow_exit_fine, checkrow_exit, showtime, show_cont1, show_cont2
  53. public    show_cont3, showtime_exit, conv, convloop, conv_cont1, conv_exit
  54. public    showword, showbyte, shownib, show_c1, display_al, click, veryend
  55. public    checkrow_ret, checkrow_exit_reshow
  56.  
  57. public    intvector, counter1, convtable, hours, mins, secs, count, message
  58. public    counter1, counter2, screen_page, attribute, flag
  59.  
  60.  
  61. ;------------------------------  SEGMENT  ---------------------------------
  62.  
  63. code    segment                    ; It must orginate at 0100h
  64.     assume    ds:code, cs:code, es:code    ; or else it can't be a .COM
  65.     org    0100h                ; file and mem-resident.
  66.  
  67. ;-------------------------------  START  ----------------------------------
  68.  
  69. start:                ; make sure DS=CS and jump around data
  70.     push    cs
  71.     pop    ds
  72.     jmp    begin
  73.  
  74. ;-------------------------------  DATA  -----------------------------------
  75. ;
  76. ;  Be sure to use the  CS:  override for all the data in this program
  77. ;  since this is a memory resident routine, and we can't be sure of the 
  78. ;  state of the [ds] register.
  79.  
  80.  
  81. intvector dw    0    ; This defines two words (a doubleword) to hold
  82.       dw    0    ; the address of the old timer routine.
  83. counter1  dw    0         ; A counter for determining when check bottom line
  84. counter2  dw    0    ; Another counter for determining when to display
  85. attribute db    0    ; Stores the screen attribute of the lower line
  86. screen_page  db    0    ; stores the screen page being viewed
  87. mode    db    0    ; stores the screen mode we are in
  88. flag    db    0    ; indicates a redisplay is neccessary
  89. hours    db    00    ; stores the hours
  90. mins    db    00    ; stores the minutes
  91. secs    db    00    ; stores the seconds
  92. count    dw    0000    ; stores the count of seconds since midnight
  93.     dw    0000
  94.  
  95. message    db    cr,lf,cr,lf,cr,lf
  96.     db    '                    26TIME Version 1.1',cr,lf,cr,lf
  97.     db    'This program was written in MASM 4.0 by Peter Nelson.  It is a memory',cr,lf
  98.     db    'resident program that occupies 1.2 k-bytes (1264) of ram.  The current time',cr,lf
  99.     db    'will be displayed on the 26th line of the screen at all times.  It will not',cr,lf
  100.     db    'interfere with graphing.  It will work only with the IBM-CGA card and',cr,lf
  101.     db    'compatibles (including compaq).',cr,lf,cr,lf,'$'
  102.  
  103. convtable db    01h,02h,04h,08h,016h,032h,064h   ; used for bin-dec convert
  104.  
  105.  
  106.  
  107. ;------------------------------  PROGRAM  ---------------------------------
  108.  
  109. begin:
  110.     mov    ah, 9            ; display logo
  111.     mov    dx, offset message
  112.     int    msdos
  113.  
  114. setvectors:
  115.     mov    ah, 035h    ; use DOS interrupt function 35h to find the
  116.     mov    al, 01Ch    ; current location of the timer interrupt
  117.     int    msdos        ; routine.  Save that location in 
  118.     mov    intvector, bx    ; [intvector].
  119.     mov    intvector+2, es
  120.  
  121.     push    cs                ; Point the timer interrupt
  122.     pop    ds                ; to my program using DOS
  123.     mov    dx, offset int18_routine    ; interrupt function 25h
  124.     mov    ah, 025h
  125.     mov    al, 01Ch
  126.     int    msdos
  127.  
  128.     mov    dx, offset veryend        ; terminate and stay in
  129.     int    terminate_stay_resident        ; memory using DOS int. 27h
  130.  
  131.  
  132.  
  133. ;------------------------------  ROUTINES  --------------------------------
  134.  
  135. int18_routine:            ; this routine is called 18.2 times/second
  136.     pushall            ; Save all the registers and the flags.
  137.  
  138.     inc    cs:counter2        ; this counter is used to 
  139.     cmp    cs:counter2, 1092    ; display time once/minute
  140.     jne    int18_cont1
  141.     mov    cs:counter2, 0
  142.     call    showtime
  143.  
  144. int18_cont1:
  145.     inc    cs:counter1        ; this counter is used to check
  146.     cmp    cs:counter1, 9        ; the row color twice/second
  147.     jne    exit
  148.     mov    cs:counter1, 0
  149.     call    checkrow
  150.     cmp    cs:flag, 0
  151.     je    exit
  152.     mov    cs:counter2, 1091    ; make time display next timer tick
  153.  
  154. exit:
  155.     popall                ; restore all the registers and flags
  156.  
  157.     jmp    dword ptr cs:[intvector]    ; branch to the original
  158.                         ; timer interrupt routine
  159.  
  160. ;--------------------------------------------------------------------------
  161.  
  162. checkrow:                ; this routine is called twice/second
  163.     mov    ah, 0Fh            ; see what video mode we are in
  164.     int    screen
  165.     cmp    al, 3
  166.     ifr a    <jmp checkrow_ret>      ; and don't print if in graphics mode
  167.     cmp    cs:mode, al        ; see if the mode changed
  168.     je    short check_cont0
  169.     mov    cs:attribute, 0        ; and make it redraw if changed    
  170.     mov    cs:mode, al        ; by making the color-check part fail
  171.  
  172. check_cont0:
  173.     mov    ah, 0Fh        ; save the cursor in the [si] reg
  174.     int    screen
  175.     mov    bl, al        ; save the mode in [bl]
  176.     mov    ah, 3
  177.     int    screen
  178.     mov        si, dx
  179.  
  180.     cmp    cs:screen_page, bh    ; if the page being viewed changes,
  181.     je    check_cont1        ; be sure to keep up with it.
  182.     mov    cs:screen_page, bh    ; change the attribute to 0
  183.     mov    cs:attribute, 0        ; so the time will be redrawn
  184.  
  185. check_cont1:
  186.     mov    di, 0        ; to indicate 80 column mode, [di]=0
  187.     cmp    bl, 2
  188.     ifr b    <mov di, 1>    ; to indicate 40 column mode, [di]=1
  189.  
  190.     mov    ah, 2        ; put the cursor at the end of the 26th
  191.     mov    dh, 25        ; line and see if there is an 'm' there.
  192.     mov    dl, 79        ; if not, then something must have 
  193.     cmp    di, 1        ; erased the screen.  set cs:attribute
  194.     ifr e    <mov dl, 39>    ; to 0 so the next little bit will catch it
  195.     int    screen        ; and redraw the bottom line
  196.     mov    ah, 8
  197.     int    screen
  198.     cmp    al, 'm'
  199.     ifr ne    <mov cs:attribute, 0>
  200.  
  201.     mov    ah, 2        ; set cursor to y=24, x=end-of-row
  202.     mov    dh, 24
  203. ;    mov    dl, 0        ; uncomment this and comment-out the next
  204.     mov    dl, 79        ; three lines if you want x=start-of-row
  205.     cmp    di, 1
  206.     ifr e    <mov dl, 39>
  207.     int    screen
  208.     mov    ah, 8        ; read the color there
  209.     int    screen
  210.     cmp    cs:attribute, ah  ; leave now if its the same
  211.     je    checkrow_exit_fine
  212.     mov    cs:attribute, ah  ; else save the new color and change screen
  213.     mov    bl, ah        ; save the color in [bl]
  214.     mov    ah, 2        ; set the cursor to the 26th line, 1st pos.
  215.     mov    dh, 25
  216.     mov    dl, 0
  217.     int    screen
  218.     mov    al, ' '        ; and print spaces across the 26th row
  219.     mov    cx, 80
  220.     cmp    di, 1
  221.     ifr e    <mov cx, 40>
  222.     mov    ah, 9
  223.     int    screen
  224.  
  225. checkrow_exit_reshow:
  226.     mov    cs:flag, 1
  227.     jmp    short checkrow_exit
  228.  
  229. checkrow_exit_fine:
  230.     mov    cs:flag, 0
  231.  
  232. checkrow_exit:
  233.     mov    ah, 0Fh        ; restore the cursor position
  234.     int    screen
  235.     mov    ah, 02
  236.     mov    dx, si        ; get position from [si]
  237.     int    screen    
  238.  
  239. checkrow_ret:
  240.     ret
  241.  
  242. ;--------------------------------------------------------------------------
  243.  
  244. showtime:            ; this is called once/minute, and when
  245.                 ; the screen color changes.
  246.     mov    ah, 0Fh        ; see what video mode we are in
  247.     int    screen
  248.     cmp    al, 3
  249.     ifr a    <jmp showtime_exit>  ; and don't print if in graphics mode
  250.  
  251.     call    click        ; make a nice 'tick' sound
  252.     
  253.     mov    ah, 0
  254.     int    time_of_day
  255.  
  256.     mov    ax, dx        ; divide ticks by 91
  257.     mov    dx, cx
  258.     mov    bx, 91
  259.     div    bx
  260.  
  261.     mov    cx, dx        ; and save the remainder in [cx]
  262.  
  263.     mov    bx, 5        ; multiply result by 5
  264.     mul    bx
  265.     mov    cs:count, ax
  266.     mov    cs:count+2, dx    ; save the result in [count]
  267.  
  268.     mov    ax, cx        ; divide the remainder (saved in [cx])
  269.     mov    dx, 0        ; by 18.  This is the same as dividing by
  270.     mov    bx, 18        ; 18.2.  I can't divide by 18 first because
  271.     div    bx        ; at midnight this would give me a result
  272.                 ; greater than 0FFFFh.  The margin of error
  273.                 ; is small.  32 seconds at midnight, less
  274.                 ; earlier in the day.
  275.  
  276.     add    ax, cs:count    ; add the result into [count] then save.
  277.     mov    cs:count, ax    ; [count] now holds the total number of     
  278.                 ; elapsed seconds since midnight (DOS).
  279.  
  280.     mov    ax, cs:count    ; divide the secs-since-midnight by 3600
  281.     mov    dx, cs:count+2    ; to get the hours since the start of the day
  282.     mov    bx, 3600
  283.     div    bx             ; hours are now in [AL].  remainder
  284.     mov    cs:hours, al     ; is in [DL]
  285.  
  286.     mov    ax, dx        ; divide the remainder by 60 to get the
  287.     mov    bl, 60        ; minutes since the start of the hour
  288.     div    bl
  289.     mov    cs:mins, al      ; is in [AH]
  290.  
  291.     mov    cs:secs, ah      ; seconds are the remainder from above.
  292.                 ; [hours] now has the current hour in
  293.                 ; military format. [mins] has the current
  294.                 ; minutes.  [secs] the current seconds.
  295.  
  296.  
  297.  
  298.     mov    ah, 0Fh        ; get current screen info
  299.     int    screen
  300.     mov    bl, al        ; save the mode in [bl]
  301.     mov    ah, 3
  302.     int    screen        
  303.     mov        si, dx        ; save the cursor position in [si]
  304.  
  305.     mov    dl, 72        ; set up x-pos to print time at.  40cols=32
  306.     cmp    bl, 2        ; 80cols=72.
  307.     ifr b    <mov dl, 32> 
  308.     
  309.     mov    bh, cs:screen_page  ; set cursor position, y=26, x=[dl] reg.
  310.     mov    ah, 2
  311.     mov    dh, 25
  312.     int    screen
  313.  
  314.     mov    dx, 03d4h    ; make the screen 26 lines long
  315.     mov    al, 6        ; this is done by setting register #6 of the
  316.     out    dx, al        ; CGA card to 26.  It is possible to get
  317.     mov    dx, 03d5h    ; as many as 29 rows of text with a CGA.
  318.     mov    al, 26
  319.     out    dx, al
  320.     
  321.     mov    al, cs:hours    ; show the time in standard format (AM/PM)
  322.     mov    di, 'a'        ; set the [di] reg to 'a'
  323.     cmp    al, 12
  324.     jbe    show_cont1
  325.     sub    al, 12        ; subtract 12 from hours, and change [di]
  326.     mov    di, 'p'        ; to 'p' if it is afternoon
  327. show_cont1:
  328.     cmp    al, 10        ; if there is only 1 digit in the hours
  329.     jae    show_cont2    ; (1:00-9:00) then don't print a leading
  330.     mov    ah, al        ; zero, so we have to call shownib instead
  331.     mov    al, ' '        ; of show byte.
  332.     call    display_al
  333.     mov    al, ah
  334.     call    conv
  335.     call    shownib
  336.     jmp    short show_cont3
  337. show_cont2:
  338.     call    conv        ; here the hours are between 10:00 and 12:00
  339.     call    showbyte    ; so print the whole byte.
  340. show_cont3:
  341.     mov    al, ':'        ; display a colon
  342.     call    display_al
  343.     mov    al, cs:mins    ; display the minutes, leading zeros are
  344.     call    conv        ; neccessary.
  345.     call    showbyte
  346. ;    mov    al, ':'        ; un-comment this to display the seconds.
  347. ;    call    display_al    ; you must also then change the position
  348. ;    mov    al, cs:secs    ; where the time is printed on the line, and
  349. ;    call    conv        ; must change the cs:counter2 check so the
  350. ;    call    showbyte    ; routine is called more frequently.
  351.     mov    al, ' '
  352.     call    display_al    ; here we display either ' am' or ' pm'
  353.     mov    ax, di
  354.     call    display_al
  355.     mov    al, 'm'
  356.     call    display_al
  357.  
  358.     mov    ah, 0Fh        ; restore the cursor position
  359.     int    screen
  360.     mov    ah, 02
  361.     mov    dx, si        ; get position from [si]
  362.     int    screen    
  363.  
  364. showtime_exit:
  365.     ret
  366.         
  367. ;--------------------------------------------------------------------------
  368.  
  369. conv:                ; in: [al] contains the number to convert.
  370.     push    bp        ; it must be less than 063h hex.  out:
  371.     push    cx        ; [al] is now converted.  [ah] is destroyed
  372.  
  373.     mov    bp, 0        ; use the DAA operand to add up the value of
  374.     mov    ah, al        ; the lower 7 bits of [al] and save the
  375.     mov    al, 0        ; result in [al].  Refer to [convtable].
  376.     mov    cx, 7
  377. convloop:
  378.     shr    ah, 1
  379.     jnc     conv_cont1   
  380.     mov    bl, cs:[bp+convtable]
  381.     add    al, bl
  382.     daa
  383. conv_cont1:
  384.     inc    bp
  385.     loop    convloop
  386.  
  387. conv_exit:
  388.     mov    ah, al
  389.     pop    cx
  390.     pop    bp
  391.     ret
  392.  
  393. ;--------------------------------------------------------------------------
  394.  
  395.  
  396. showword:            ;This routine displays a word (AX)
  397.     push    ax
  398.     push    cx
  399.     mov     cl,8
  400.     shr    ax,cl
  401.     call    showbyte
  402.     pop    cx
  403.     pop    ax
  404.  
  405. showbyte:            ;This routine displays a byte (AL)
  406.     push    ax
  407.     push    cx
  408.     mov     cl,4
  409.     shr    al,cl
  410.     call    shownib
  411.     pop    cx
  412.     pop    ax
  413.     
  414. shownib:            ;This routine displays lower nibble(AL)
  415.     push    ax
  416.     push    dx
  417.  
  418.     and     al, 0Fh
  419.     mov     dl,'0'
  420.      cmp     al,0Ah        ;Hm.. need higher OR value? for hex digit
  421.     jl    show_c1
  422.     mov     dl,('A'-10)
  423.  
  424. show_c1:
  425.     add    dl,al
  426.     mov    al, dl
  427.     call    display_al
  428.     pop    dx
  429.     pop    ax
  430.     ret
  431.  
  432. display_al:
  433.     push    ax            ;This routines displays an ascii byte (AL)
  434.     push    bx
  435.     push    bp
  436.     pushf
  437.  
  438.     push    ax
  439.     mov    ah, 0Fh
  440.     int    screen
  441.     mov    ah, 08h
  442.     int    screen
  443.     mov    bl, al
  444.     pop    ax
  445.     mov    ah, 0Eh
  446.     int    screen
  447.  
  448.     popf
  449.     pop    bp
  450.     pop    bx
  451.     pop    ax
  452.     ret
  453.  
  454. ;--------------------------------------------------------------------------
  455.  
  456. click:            ; IN=none, OUT=none, all regs preserved.
  457.     push    ax
  458.     push    cx
  459.  
  460.     mov    al, 10110110b
  461.     out    timer+3, al
  462.     mov    ax, 0777h     ; this is the frequency of the tone
  463.     out    timer+2, al
  464.     mov    al, ah
  465.     out    timer+2, al
  466.     in    al, port_b
  467.     mov    ah, al
  468.     or    al, 03h
  469.     out    port_b, al
  470.     mov    cx, 0018h     ; this is the duration of the tone
  471.     loop    $
  472.     mov    al, ah
  473.     out    port_b, al
  474.     
  475.     pop    cx
  476.     pop    ax
  477.     ret    
  478.  
  479.  
  480. ;--------------------------------  ENDS  ----------------------------------
  481.  
  482.          db    0        ; this is here for the DOS terminate-and-
  483. veryend:            ; stay-resident function to work properly.
  484. code    ends
  485.     end    start
  486. ;------------------------------  ROUTINES  --------------------------------
  487.